package com.yanqu.road.server.manger.kowloon;

import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.kowloon.config.KowloonBuildingConfig;
import com.yanqu.road.entity.kowloon.config.KowloonEliminateGuideConfig;
import com.yanqu.road.entity.kowloon.config.KowloonMissionRoadConfig;
import com.yanqu.road.entity.kowloon.config.KowloonNpcConfig;
import com.yanqu.road.entity.kowloon.enums.eKowloonBlockEffectType;
import com.yanqu.road.entity.kowloon.enums.eKowloonBlockType;
import com.yanqu.road.entity.kowloon.enums.eKowloonNpcType;
import com.yanqu.road.entity.kowloon.sanxiao.KowloonChooseHeroData;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.model.kowloon.KowloonConfig;
import com.yanqu.road.entity.kowloon.enums.eKowloonOpType;
import com.yanqu.road.entity.kowloon.sanxiao.KowloonBlock;
import com.yanqu.road.entity.kowloon.sanxiao.KowloonGameData;
import com.yanqu.road.logic.bussiness.kowloon.KowloonBusiness;
import com.yanqu.road.logic.model.kowloon.sanxiao.KowloonBlockEffect;
import com.yanqu.road.logic.model.kowloon.sanxiao.KowloonEliminateParam;
import com.yanqu.road.logic.model.kowloon.sanxiao.KowloonEliminateResult;
import com.yanqu.road.logic.model.kowloon.sanxiao.KowloonEliminateTip;
import com.yanqu.road.pb.kowloon.KowloonProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import com.yanqu.road.server.pb.KowloonPb;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 九龙城寨
 */
public class KowloonMgr extends TempMgr {
    private static KowloonConfig config = null;
    //chapterId
    private static Map<Integer, KowloonProto.KowloonGameDataMsg.Builder> guideShowMsgMap = new ConcurrentHashMap<>();
    //chapterId
    private static Map<Integer, KowloonGameData> guideGameDataMap = new ConcurrentHashMap<>();

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        KowloonConfig loadConfig = new KowloonConfig();
        Map<Integer, Map<Integer, KowloonBuildingConfig>> buildingConfigMap = KowloonBusiness.getKowloonBuildingConfigMap();
        Map<Integer, Map<Integer, KowloonMissionRoadConfig>> missionRoadConfigMap = KowloonBusiness.getKowloonMissionRoadConfigMap();
        Map<eKowloonNpcType, Map<Integer, Map<Integer, Map<Integer, KowloonNpcConfig>>>> npcConfigMap = KowloonBusiness.getKowloonNpcConfigMap();
        loadConfig.initConfig(buildingConfigMap, missionRoadConfigMap, npcConfigMap, SkillMgr.getKowloonSkillInfoMap());
        config = loadConfig;

        initGuideShowMsg();
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    public static KowloonConfig getConfig() {
        return config;
    }


    public static int getKowloonMoraleSkillId(int level) {
        SkillInfo skillInfo = getKowloonMoraleSkillInfo(level);
        return skillInfo == null ? 0 : skillInfo.getId();
    }

    public static SkillInfo getKowloonMoraleSkillInfo(int level) {
        int skillIdx = level - 1;
        List<SkillInfo> skillInfoList = SkillMgr.getSkillInfoListByType(eSkillType.KowloonMorale.getValue());
//        skillInfoList.sort(Comparator.comparingInt(SkillInfo::getId));
        if (skillIdx > skillInfoList.size() - 1 || skillIdx < 0) {
            return null;
        }
        return skillInfoList.get(skillIdx);
    }


    /**
     * 获取升级技能消耗
     */
    public static String getKowloonSkillUpgradeCost(int curLevel, int skillId) {
        if (config == null) {
            return null;
        }
        SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
        if (skillInfo == null) {
            return null;
        }
        SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), curLevel);
        if (skillUpgradeInfo == null) {
            return null;
        }
        return skillInfo.getConsumeGoodsId() + "=" + skillUpgradeInfo.getConsumeCount();
    }

    /**
     * 获取升级技能参数
     */
    public static List<Integer> getKowloonSkillParam(int skillId) {
        SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
        if (skillInfo == null) {
            return null;
        }
        return skillInfo.getParamList();
    }


    public static void main(String[] args) {
        KowloonGameData gameData = new KowloonGameData();
        gameData.setBeginTime(DateHelper.getCurrentTime());
//        gameData.setBlockList(getRandomBlockList());
//        gameData.setBlockList(KowloonEliminateLogic.getTestListList());
        System.out.println("初始盘面----");
        printfGameData(gameData);
        System.out.println("开始消除----");
        for (int i = 0; i < 10; i++) {
            KowloonEliminateParam param = new KowloonEliminateParam();
            param.setGameData(gameData);
            param.setFirstMove(i == 0);
            KowloonEliminateTip eliminateTip = KowloonEliminateLogic.getEliminateTip(param, param.getGameData().getBlockList());
//            eliminateTip = null;
            if (null != eliminateTip) {
                param.setFromX(eliminateTip.getFrom().getX());
                param.setFromY(eliminateTip.getFrom().getY());
                param.setToX(eliminateTip.getTo().getX());
                param.setToY(eliminateTip.getTo().getY());
                param.setType(eKowloonOpType.Exchange.getValue());
            } else {
                int fromY = (int) RandomHelper.nextLong(param.getGameData().getBlockList().size());
                int fromX = (int) RandomHelper.nextLong(param.getGameData().getBlockList().get(fromY).size());
                param.setFromX(fromX);
                param.setFromY(fromY);
                param.setType(eKowloonOpType.MoveOut.getValue());
            }

            KowloonEliminateResult moveResult = KowloonEliminateLogic.moveBlock(param);
            gameData.setUseStep(gameData.getUseStep() + 1);
            System.out.println(String.format("使用步数%d----行为%d,(%d,%d)=>(%d,%d)", gameData.getUseStep(), param.getType(), param.getFromY(), param.getFromX(), param.getToY(), param.getToX()));
            printfGameData(gameData);
        }

    }

    public static void printfGameData(KowloonGameData gameData) {
        System.out.println("---------------------------");
        List<String> lineList = new ArrayList<>();
        for (int y = gameData.getBlockList().size() - 1; y >= 0; y--) {
            String xStr = "" + y + "---";
            for (int x = 0; x < gameData.getBlockList().get(y).size(); x++) {
                xStr += "(" + String.format("%d", gameData.getBlockList().get(y).get(x).getColor()) + "," + gameData.getBlockList().get(y).get(x).getLevel() + ")";
                KowloonBlock block = gameData.getBlockList().get(y).get(x);
                if (block.getX() != x || block.getY() != y) {
                    System.out.println("格子错误！！");
                }
            }
            lineList.add(xStr);
        }
        for (String lineStr : lineList) {
            System.out.println(lineStr);
        }
        System.out.println("---------------------------");
    }

    public static void initGuideShowMsg() {
        for (KowloonEliminateGuideConfig guideConfig : config.getGuideConfigMap().values()) {
            KowloonMissionRoadConfig guideMissionRoadConfig = config.getKowloonMissionRoadConfig(guideConfig.getMissionRoadId(), 1);
            //初始固定盘面
            KowloonGameData gameData = new KowloonGameData();


            gameData.setMaxHp(GameConfig.KOWLOON_BOOTH_HP);
            gameData.setHp(gameData.getMaxHp());
            gameData.setChapterId(guideMissionRoadConfig.getMissionRoadId());
            gameData.setSectionId(guideMissionRoadConfig.getWave());
            gameData.setLeftStep(guideMissionRoadConfig.getStepNum());

            // 上阵好汉
            List<KowloonChooseHeroData> chooseHeroDataList = new ArrayList<>();
            String[] split = GameConfig.KOWLOON_GUIDE_HERO_LIST.split("\\|");
            int index = 0;
            for (String heroStr : split) {
                List<Integer> heroAttrs = StringUtils.stringToIntegerList(heroStr, "=");
                KowloonChooseHeroData heroData = new KowloonChooseHeroData(heroAttrs.get(0), heroAttrs.get(1), index++);
                chooseHeroDataList.add(heroData);
            }
            gameData.setChooseHeroList(chooseHeroDataList);

            gameData.setBlockList(KowloonConfig.getGuideBlockList(chooseHeroDataList, guideConfig.getColors()));

            KowloonEliminateParam param = new KowloonEliminateParam();
            param.setConfig(KowloonMgr.getConfig());
            param.setGuide(true);
            param.setGameData(gameData);

            KowloonProto.KowloonGameDataMsg.Builder gameDataMsg = KowloonPb.parseKowloonGameDataMsg(gameData);

            List<KowloonProto.KowloonShowMsg> showMsgList = new ArrayList<>();

            for (List<Integer> operateAttrs : guideConfig.getOperateList()) {
                int guideId = operateAttrs.get(0);
                int opType = operateAttrs.get(1);
                int fromX = operateAttrs.get(2);
                int fromY = operateAttrs.get(3);
                int toX = operateAttrs.get(4);
                int toY = operateAttrs.get(5);
                param.setType(opType);
                param.setFromX(fromX);
                param.setFromY(fromY);
                param.setToX(toX);
                param.setToY(toY);

                KowloonProto.KowloonShowMsg.Builder guideShowMsg = KowloonProto.KowloonShowMsg.newBuilder();
                KowloonBlockEffect blockEffect = new KowloonBlockEffect(eKowloonBlockEffectType.GuideStep.getValue());
                blockEffect.addValue(guideId);
                blockEffect.addValue(opType);
                blockEffect.addValue(fromX);
                blockEffect.addValue(fromY);
                blockEffect.addValue(toX);
                blockEffect.addValue(toY);
                blockEffect.getBlockList().add(gameData.getBlockList().get(fromY).get(fromX));

                if (opType == eKowloonOpType.Exchange.getValue()) {

//                    printfGameData(param.getGameData());

                    KowloonEliminateTip eliminateTip = KowloonEliminateLogic.getOperateEliminateTip(param, param.getGameData().getBlockList());
                    if (null != eliminateTip) {
                        blockEffect.setBlockList(eliminateTip.getAllBlockList());
                    }
                }

                guideShowMsg.addEffects(KowloonPb.parseEffectMsg(blockEffect));
                showMsgList.add(guideShowMsg.build()); //加入引导步骤消息

                if (opType == eKowloonOpType.Exchange.getValue()
                        || opType == eKowloonOpType.MoveOut.getValue()
                        || opType == eKowloonOpType.Destroy.getValue()) {
                    KowloonEliminateResult eliminateResult = KowloonEliminateLogic.moveBlock(param);
                    //更新步数
                    param.getGameData().decLeftStep();
                    showMsgList.addAll(KowloonPb.parseShowListMsg(eliminateResult.getShowResultList()));
                }
            }

//            printfGameData(param.getGameData());

            KowloonProto.KowloonOperateRespMsg.Builder guideMsg = KowloonProto.KowloonOperateRespMsg.newBuilder();
            guideMsg.setRet(0);
            guideMsg.addAllShow(showMsgList);
            guideMsg.setGameData(KowloonPb.parseKowloonGameDataMsg(param.getGameData()));
            gameDataMsg.setShowData(guideMsg);
            guideShowMsgMap.put(guideMissionRoadConfig.getMissionRoadId(), gameDataMsg);
            guideGameDataMap.put(guideMissionRoadConfig.getMissionRoadId(), param.getGameData());
        }
    }

    public static KowloonProto.KowloonGameDataMsg.Builder getGuideDataMsg(int chapterId) {
        return guideShowMsgMap.get(chapterId);
    }

    public static KowloonGameData cloneGuideGameData(int chapterId) {
        KowloonGameData gameData = guideGameDataMap.get(chapterId);
        if (null != gameData) {
            return gameData.clone();
        }
        return null;
    }

}
